home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / manyth31 / gif.c < prev    next >
C/C++ Source or Header  |  1994-07-28  |  24KB  |  1,032 lines

  1. /* $change:Code cleanup, minor fixes.$ */
  2. /*
  3. **    $id: ssvcid gif.c 1.0 08/03/92 10:01 am$
  4. **        Read a Compuserve GIF file into a DIB.
  5. **
  6. **    (C) 1992-1993    Larry Widing
  7. */
  8. #define NOCOMM
  9. #define NOKANJI
  10. #include <windows.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include    <malloc.h>
  14. #include    "bitmaps.h"
  15.  
  16. #define    SEG_CBUF        01
  17. #define    FASTCALLS    01
  18. #define    GET_BYTES    01
  19. #define    PAL_SHIFT    0
  20.  
  21. /*
  22. **    Local functions
  23. */
  24. static short NEAR    decoder(short linewidth);
  25. static short        init_exp(short  size);
  26. static short NEAR    get_next_code(void);
  27. static void            inittable(void);
  28. static void            close_file(void);
  29.  
  30. /*
  31. **    Local variables
  32. */
  33. static int                        rowcount;        /* row counter for screen */
  34. static int                        hin = NULL;
  35. static unsigned int            height;
  36.  
  37. static unsigned char            dacbox[256][3];            /* Video-DAC (filled in by SETVIDEO) */
  38.  
  39. static unsigned char            decoderline[2049];        /* write-line routines use this */
  40. static unsigned char            win_andmask[8];
  41. static unsigned char            win_notmask[8];
  42. static unsigned char            win_bitshift[8];
  43.  
  44. static int                        xdots, ydots, colors;
  45. static int                        win_xdots, win_ydots;
  46. static unsigned char huge    *pixels;                     /* the device-independent bitmap pixels */
  47. static int                        pixels_per_byte;        /* pixels/byte in the pixmap */
  48. static long                        pixels_per_bytem1;        /* pixels / byte - 1 (for ANDing) */
  49. static int                        pixelshift_per_byte;    /* 0, 1, 2, or 3 */
  50. static int                        bytes_per_pixelline;    /* pixels/line / pixels/byte */
  51. static long                        win_bitmapsize;            /* bitmap size, in bytes */
  52. static int                        bad_code_count = 0;        /* needed by decoder module */
  53. #if    SEG_CBUF
  54. static BYTE _seg                *cbuf = NULL;
  55. static unsigned int            gbuf = 0;
  56. #else
  57. static BYTE FAR                *cbuf = NULL;
  58. static BYTE FAR                *gbuf = NULL;
  59. #endif
  60. static HANDLE                    hcbuf = NULL;
  61. static unsigned int            gbn = 0;
  62.  
  63. #define    cbufsize    (32u * 1024u)        // (16u * 1024u)
  64.  
  65. static int NEAR
  66. get_byte(void)
  67. {
  68.     if (gbn == 0)
  69.     {
  70.         gbn = _lread(hin,cbuf,cbufsize);
  71. #if    SEG_CBUF
  72.         gbuf = 0;
  73. #else
  74.         gbuf = NULL;
  75. #endif
  76.     }
  77.  
  78.     if (gbn)
  79.     {
  80.         --gbn;
  81. #if    SEG_CBUF
  82.         return (cbuf[gbuf++]) & 0x00ff;
  83. #else
  84.         return (*gbuf++) & 0x00ff;
  85. #endif
  86.     }
  87.     else
  88.         return (-1);
  89. }
  90.  
  91. #if    GET_BYTES
  92. static int NEAR 
  93. get_bytes(unsigned int count, char *dest)
  94. {
  95.     int    count2 = count;
  96.  
  97.     if (count <= 0)
  98.     {
  99.         return count;
  100.     }
  101.  
  102.     while (count)
  103.     {
  104.         if (gbn == 0)
  105.         {
  106.             gbn = _lread(hin,cbuf,cbufsize);
  107. #if    SEG_CBUF
  108.             gbuf = NULL;
  109. #else
  110.             gbuf = cbuf;
  111. #endif
  112.  
  113.             if (!gbn)
  114.                 return -1;
  115.         }
  116.  
  117.         if (gbn >= count)
  118.         {
  119.             if (dest != NULL)
  120.             {
  121. #if    SEG_CBUF
  122.                 memcpy(dest, cbuf + gbuf, count);
  123. #else
  124.                 memcpy(dest, gbuf, count);
  125. #endif
  126.             }
  127.             gbuf += count;
  128.             gbn -= count;
  129.             count = 0;
  130.         }
  131.         else
  132.         {
  133.             if (dest != NULL)
  134.             {
  135. #if    SEG_CBUF
  136.                 memcpy(dest, cbuf + gbuf, gbn);
  137. #else
  138.                 memcpy(dest, gbuf, gbn);
  139. #endif
  140.             }
  141.             count -= gbn;
  142.             dest += gbn;
  143.             gbn = 0;
  144.         }
  145.     }
  146.  
  147.     return count2;
  148. }
  149. #endif
  150.  
  151. static void NEAR 
  152. putcolor(int x, int y, int color)
  153. {
  154.     long i;
  155.  
  156.     i = win_ydots - 1 - y;
  157.     i = (i * win_xdots) + x;
  158.  
  159.     if (x >= 0 && x < xdots && y >= 0 && y < ydots)
  160.     {
  161.         if (pixelshift_per_byte == 0)
  162.         {
  163.             pixels[i] = color % colors;
  164.         }
  165.         else
  166.         {
  167.             unsigned int j;
  168.  
  169.             j = i & (unsigned int)pixels_per_bytem1;
  170.             i = i >> pixelshift_per_byte;
  171.             pixels[i] = (pixels[i] & win_notmask[j]) + 
  172.                  (((unsigned char) (color % colors)) << win_bitshift[j]);
  173.         }
  174.     }
  175. }
  176.  
  177. static int NEAR 
  178. put_line(int rownum, int leftpt, int rightpt, unsigned char *localvalues)
  179. {
  180.     int    i, len;
  181.     long    startloc;
  182.  
  183.     len = rightpt - leftpt;
  184.     if (rightpt >= xdots)
  185.     {
  186.         len = xdots - leftpt;
  187.     }
  188.     startloc = win_ydots - 1 - rownum;
  189.     startloc = (startloc * win_xdots) + leftpt;
  190.  
  191.     if (rownum < 0 || rownum >= ydots || leftpt < 0)
  192.     {
  193.         return (0);
  194.     }
  195.  
  196.     if (pixelshift_per_byte == 0)
  197.     {
  198.         /*
  199.         **    Done this way because _fmemcpy() does not handle HUGE pointers
  200.         **    that can wrap over a selector/segment boundry.
  201.         */
  202.         unsigned char huge    *ptr = pixels + startloc;
  203.  
  204.         if (HIWORD(ptr) != HIWORD(ptr + len))
  205.         {
  206.             char    *src = (char *)localvalues;
  207.  
  208.             while (len--)
  209.                 *ptr++ = *src++;
  210.         }
  211.         else
  212.         {
  213.             _fmemcpy(ptr, localvalues, len);
  214.         }
  215.     }
  216.     else
  217.     {
  218.         unsigned int    j;
  219.         long                k;
  220.  
  221.         for (i = 0 ;  i <= len ;  i++)
  222.         {
  223.             k = startloc + i;
  224.             j = k & (unsigned int)pixels_per_bytem1;
  225.             k = k >> pixelshift_per_byte;
  226.             pixels[k] = (pixels[k] & win_notmask[j]) + 
  227.                  (((unsigned char) (localvalues[i] % colors)) << win_bitshift[j]);
  228.         }
  229.     }
  230.     putcolor(leftpt, rownum, localvalues[0]);
  231.  
  232.     return (1);
  233. }
  234.  
  235. static int NEAR 
  236. out_line(unsigned char *localvalues, int numberofdots)
  237. {
  238.     return (put_line(rowcount++, 0, numberofdots, localvalues));
  239. }
  240.  
  241.  
  242. /*
  243. **    Main entry decoder
  244. */
  245.  
  246. HDIB
  247. ReadGifFile(const char FAR *filename)
  248. {
  249.     HDIB                        dib = (HANDLE)NULL, hbiCurrent;
  250.     unsigned                    numcolors;
  251.     unsigned char            buffer[16];
  252.     unsigned                    width, finished;
  253.     LPBITMAPINFOHEADER    lpbi;
  254.     RGBQUAD FAR                *pRgb;
  255.     int                        status = 0;
  256.     int                        i, j, planes;
  257.     DWORD                        dwBits, dwLen;
  258.    OFSTRUCT                    of;
  259.  
  260.    /* initialize the row count for write-lines */
  261.     rowcount = 0;
  262.  
  263.    /* zero out the full write-line */
  264.     for (width = 0 ;  width < 2049 ;  width++)
  265.         decoderline[width] = 0;
  266.  
  267.    /* Open the file -- changed to OpenFile by mh */
  268.    hin = OpenFile ((LPSTR)filename, (LPOFSTRUCT)&of, OF_READ);
  269.     if (hin == -1)
  270.     {
  271.         return FALSE;
  272.     }
  273.  
  274.     hcbuf = GlobalAlloc(GHND,cbufsize);
  275.     cbuf = (BYTE FAR *)GlobalLock(hcbuf);
  276.     if (cbuf == NULL)
  277.     {
  278.         close_file();
  279.         return FALSE;
  280.     }
  281.     gbn = 0;
  282. #if    SEG_CBUF
  283.     gbuf = 0;
  284. #else
  285.     gbuf = NULL;
  286. #endif
  287.  
  288.    /* Get the screen description */
  289.     for (i = 0 ; i < 13 ; i++)
  290.     {
  291.         buffer[i] = (unsigned char) status = get_byte();
  292.         if (status < 0)
  293.         {
  294.             close_file();
  295.             return FALSE;
  296.         }
  297.     }
  298.  
  299.     if (strncmp((char *)buffer, "GIF87a", 3) ||     /* use updated GIF specs */
  300.          buffer[3] < '0' || buffer[3] > '9' || 
  301.          buffer[4] < '0' || buffer[4] > '9' || 
  302.          buffer[5] < 'A' || buffer[5] > 'z')
  303.     {
  304.         close_file();
  305.         return FALSE;
  306.     }
  307.  
  308.     planes = (buffer[10] & 0xF) + 1;
  309.  
  310.     if ((buffer[10] & 0x80) == 0)    /* color map (better be!) */
  311.     {
  312.         close_file();
  313.         return FALSE;
  314.     }
  315.     numcolors = 1 << planes;
  316.  
  317. #if    GET_BYTES
  318.     if (numcolors * 3 == get_bytes(numcolors * 3, dacbox))
  319.     {
  320. #if    PAL_SHIFT
  321.         for (i = 0 ; i < numcolors ; ++i)
  322.         {
  323.             for (j = 0 ; j < 3 ; ++j)
  324.             {
  325.                 dacbox[i][j] >>= 2;
  326.             }
  327.         }
  328. #endif
  329.     }
  330.     else
  331.     {
  332.         close_file();
  333.         return FALSE;
  334.     }
  335. #else
  336.     for (i = 0 ;  i < numcolors ;  i++)
  337.     {
  338.         for (j = 0 ;  j < 3 ;  j++)
  339.         {
  340.             status = get_byte();
  341.             if (status < 0)
  342.             {
  343.                 close_file();
  344.                 return FALSE;
  345.             }
  346.  
  347.             dacbox[i][j] = (status & 0x00ff) >> 2;
  348.         }
  349.     }
  350. #endif
  351.  
  352.    /* Now display one or more GIF objects */
  353.     finished = 0;
  354.     while (!finished)
  355.     {
  356.         switch (get_byte())
  357.         {
  358.             case ';':                /* End of the GIF dataset */
  359.                 finished = 1;
  360.                 status = 0;
  361.                 break;
  362.  
  363.             case '!':                /* GIF Extension Block */
  364.                 get_byte();        /* read (and ignore) the ID */
  365.                 while ((i = get_byte()) > 0)    /* get the data length */
  366. #if    GET_BYTES
  367.                     get_bytes(i, NULL);
  368. #else
  369.                     for (j = 0;  j < i;  j++)
  370.                         get_byte();    /* flush the data */
  371. #endif
  372.                 break;
  373.  
  374.             case ',':
  375.                  /*
  376.                    * Start of an image object. Read the image description.
  377.                    */
  378.  
  379. #if    GET_BYTES
  380.                 if (9 != get_bytes(9, buffer))
  381.                 {
  382.                     status = -1;
  383.                 }
  384.                 else
  385.                 {
  386.                     status = 0;
  387.                 }
  388. #else
  389.                 for (i = 0;  i < 9;  i++)
  390.                 {
  391.                     buffer[i] = (unsigned char) status = get_byte();
  392.                     if (status < 0)
  393.                     {
  394.                         status = -1;
  395.                         break;
  396.                     }
  397.                 }
  398. #endif
  399.                 if (status < 0)
  400.                 {
  401.                     finished = 1;
  402.                     break;
  403.                 }
  404.  
  405.                 width = buffer[4] | (buffer[5] << 8);
  406.                 height = buffer[6] | (buffer[7] << 8);
  407.                 // fill in DIB stuff
  408.                 xdots = width;
  409.                 ydots = height;
  410.                 colors = numcolors;
  411.                 if (colors > 16)
  412.                     colors = 256;
  413.                 if (colors > 2 && colors < 16)
  414.                     colors = 16;
  415.                 win_xdots = (xdots + 3) & 0xFFFC;
  416.                 win_ydots = ydots;
  417.                 pixelshift_per_byte = 0;
  418.